home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
RTF
/
RichText.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
24KB
|
967 lines
/* $Header: /usr/people/pcd/Src/RTF/RCS/RichText.c,v 1.1 92/11/23 12:58:54 pcd Exp Locker: pcd $
* from: SCCSID[] = "OSF/Motif: @(#)DrawingA.c 3.19 91/01/10";
*/
#include "RichTextP.h"
#include <X11/Xatom.h>
#include "debug.h"
/* Internal procedures:
*/
static void ClassPartInitialize( WidgetClass class);
static void Initialize( XcRichTextWidget request,
XcRichTextWidget new);
static void Redisplay( XcRichTextWidget da, XEvent * event,
Region region);
static void Resize( XcRichTextWidget da);
static void Destroy( XcRichTextWidget da);
static Boolean SetValues( XcRichTextWidget current,
XcRichTextWidget request,
XcRichTextWidget new);
static void Realize(Widget w, Mask *valueMask,
XSetWindowAttributes *attributes);
static int
InvertSelection(XcRichTextWidget w);
static int
InvertDifference(XcRichTextWidget w,
int rx, int ry,
unsigned rw, unsigned rh);
/* Default translation table and action list */
/*@@ button 2 for link action? */
/*@@ double click stuff? */
static char defaultTranslations[] =
"<Btn1Down>: select-start() \n\
<Btn1Motion>: extend-adjust() \n\
<Btn1Up>: extend-end(PRIMARY, CUT_BUFFER0) MotionVerify()\n\
<Btn3Down>: extend-start() \n\
<Btn3Motion>: extend-adjust() \n\
<Btn3Up>: extend-end(PRIMARY, CUT_BUFFER0) \
";
/* Resource definitions for RichText
*/
static XtResource resources[] =
{
{
XmNfontList,
XmCFontList, XmRFontList, sizeof (XmFontList),
XtOffset (XcRichTextWidget, rich_text.fontList),
XmRImmediate, (caddr_t) NULL,
},
{
XmNmotionVerifyCallback,
XmCCallback, XmRCallback, sizeof (XtCallbackList),
XtOffset (XcRichTextWidget, rich_text.motion_verify_callback),
XmRImmediate, (caddr_t) NULL,
},
{
XmNmarginHeight,
XmCMarginHeight,
XmRVerticalDimension,
sizeof (Dimension),
XtOffset (XcRichTextWidget, rich_text.margin_height),
XmRImmediate,
(caddr_t) 10,
},
{
XmNmarginWidth,
XmCMarginWidth,
XmRHorizontalDimension,
sizeof (Dimension),
XtOffset (XcRichTextWidget, rich_text.margin_width),
XmRImmediate,
(caddr_t) 10,
},
{
XcNrtf,
XcCRtf, XmRBoolean, sizeof (Boolean),
XtOffset (XcRichTextWidget, rich_text.rtf),
XmRImmediate, (caddr_t) 0,
},
{
XmNvalue,
XmCValue, XmRString, sizeof (String),
XtOffset (XcRichTextWidget, rich_text.value),
XmRString, (caddr_t) NULL,
},
};
static void MotionVerify(Widget, XEvent*, String*, Cardinal*);
static void SelectStart(Widget, XEvent*, String*, Cardinal*);
static void ExtendStart(Widget, XEvent*, String*, Cardinal*);
static void ExtendEnd(Widget, XEvent*, String*, Cardinal*);
static void ExtendAdjust(Widget, XEvent*, String*, Cardinal*);
static XtActionsRec actionsList[] =
{
{ "enter", (XtActionProc) _XmPrimitiveEnter },
{ "leave", (XtActionProc) _XmPrimitiveLeave },
{ "Help", (XtActionProc) _XmPrimitiveHelp }, /* Motif 1.0 */
{ "select-start", (XtActionProc) SelectStart },
{ "extend-start", (XtActionProc) ExtendStart },
{ "extend-adjust", (XtActionProc) ExtendAdjust },
{ "extend-end", (XtActionProc) ExtendEnd },
{ "MotionVerify", (XtActionProc) MotionVerify }
};
/****************************************************************
*
* Full class record constant
*
****************************************************************/
externaldef( xcrichtextclassrec) XcRichTextClassRec
xcRichTextClassRec =
{
{ /* core_class fields */
(WidgetClass) &xmPrimitiveClassRec, /* superclass */
"XcRichText", /* class_name */
sizeof(XcRichTextRec), /* widget_size */
NULL, /* class_initialize */
ClassPartInitialize, /* class_part_init */
FALSE, /* class_inited */
(XtInitProc) Initialize, /* initialize */
NULL, /* initialize_hook */
Realize, /* realize */
actionsList, /* actions */
XtNumber(actionsList), /* num_actions */
resources, /* resources */
XtNumber(resources), /* num_resources */
NULLQUARK, /* xrm_class */
TRUE, /* compress_motion */
XtExposeCompressMaximal, /* compress_exposure */
TRUE, /* compress_enterlv */
FALSE, /* visible_interest */
(XtWidgetProc)Destroy, /* destroy */
(XtWidgetProc) Resize, /* resize */
(XtExposeProc) Redisplay, /* expose */
(XtSetValuesFunc) SetValues, /* set_values */
NULL, /* set_values_hook */
(XtAlmostProc) _XtInherit, /* set_values_almost */
NULL, /* get_values_hook */
NULL, /* accept_focus */
XtVersion, /* version */
NULL, /* callback_private */
defaultTranslations, /* tm_table */
NULL, /* query_geometry */
NULL, /* display_accelerator */
NULL, /* extension */
},
{ /* composite_class fields */
(XtWidgetProc) _XtInherit, /* primitive border highlight */
(XtWidgetProc) _XtInherit, /* primitive border unhighlight */
NULL, /* translations */
NULL, /* arm_and_activate */
NULL, /* get resources */
0, /* num get_resources */
NULL, /* extension */
},
};
externaldef( xmrichtextwidgetclass) WidgetClass xcRichTextWidgetClass
= (WidgetClass) &xcRichTextClassRec ;
/****************************************************************/
static void
ClassPartInitialize(
WidgetClass class)
{
_XmFastSubclassInit( class, XmPRIMITIVE_BIT) ;
return ;
}
/****************************************************************/
static void
CopyFontList(XcRichTextWidget new)
{
if (new->rich_text.fontList == NULL){
XFontStruct *fs;
XmStringCharSet cset = (XmStringCharSet) XmSTRING_DEFAULT_CHARSET;
fs = XLoadQueryFont(XtDisplay(new), "fixed");
new->rich_text.fontList = XmFontListCreate (fs, cset);
}
/* Make a local copy of the font list */
else{
new->rich_text.fontList = XmFontListCopy(new->rich_text.fontList);
}
}
static void
Initialize(
XcRichTextWidget request,
XcRichTextWidget new)
/****************
* Ensure that the width and height are not 0.
****************/
{
/****************/
Display* disp = XtDisplay(new);
void* flow;
int f;
CopyFontList(new);
new->rich_text.value = XtNewString(new->rich_text.value);
new->rich_text.bytes = new->rich_text.value ? strlen(new->rich_text.value):0;
new->rich_text.point = new->rich_text.mark = 0; /* no selection */
new->rich_text.invert = 0;
new->rich_text.flow = flow = XTextView_create(XtDisplay(new),
(void*)new);
Resize(new);
#if 0
/* FINDME - This codes forces you to have text in the widget prior to
setting a minimum height. Unfortunately, it doesn't reset the height
properly, when you do set text there ... until you reset the
XmNheight resource. */
if(XTextView_string(flow, new->rich_text.value, new->rich_text.rtf)){
/* find out how tall flow is after formatting. */
new->core.height = XTextView_height(flow)
+ 2 * new->rich_text.margin_height;
/* @@ not all text may fit! */
}
#endif
return ;
}
/****************************************************************/
static void
Destroy(
XcRichTextWidget new)
{
/****************/
int f;
if(new->rich_text.value) XtFree(new->rich_text.value);
if(new->rich_text.fontList) XmFontListFree(new->rich_text.fontList);
if(new->rich_text.flow)
XTextView_destroy(new->rich_text.flow);
}
/****************************************************************/
static void
Redisplay(
XcRichTextWidget da,
XEvent * event,
Region region)
/****************
* General redisplay function called on exposure events.
****************/
{
XcRichTextPart* p = &da->rich_text;
long s, e;
int flicker;
int* x = da->rich_text.sx;
int* y = da->rich_text.sy;
if(p->point < p->mark){
s = p->point;
e = p->mark;
}else{
s = p->mark;
e = p->point;
}
flicker = s != e
&& y[0] <= event->xexpose.y+event->xexpose.height
&& y[3] >= event->xexpose.y;
if(flicker){
XClearArea(XtDisplay((Widget)da), XtWindow((Widget)da),
event->xexpose.x,
event->xexpose.y,
event->xexpose.width,
event->xexpose.height,
0);
InvertDifference(da,
event->xexpose.x,
event->xexpose.y,
event->xexpose.width,
event->xexpose.height);
}
XTextView_render(da->rich_text.flow,
event->xexpose.x,
event->xexpose.y,
event->xexpose.width,
event->xexpose.height);
if(flicker)
InvertSelection(da);
}
/****************************************************************/
static void
Resize(
XcRichTextWidget da)
/****************
* resize the XFlow
****************/
{
XTextView_resize(da->rich_text.flow,
da->rich_text.margin_width,
da->rich_text.margin_height,
da->core.width - da->rich_text.margin_width*2,
da->core.height - da->rich_text.margin_height*2);
return ;
}
/****************************************************************/
static void Realize(w, p_valueMask, attributes)
Widget w;
Mask *p_valueMask;
XSetWindowAttributes *attributes;
{
Mask valueMask = *p_valueMask;
valueMask |= CWBitGravity | CWDontPropagate;
attributes->bit_gravity = NorthWestGravity;
attributes->do_not_propagate_mask =
ButtonPressMask | ButtonReleaseMask |
KeyPressMask | KeyReleaseMask | PointerMotionMask;
XtCreateWindow (w, InputOutput, CopyFromParent, valueMask, attributes);
XTextView_drawable(((XcRichTextWidget)w)->rich_text.flow,
XtWindow(w),
((XcRichTextWidget)w)->core.depth);
}
/****************************************************************/
static Boolean
SetValues(
XcRichTextWidget current,
XcRichTextWidget request,
XcRichTextWidget new)
/****************
* change font, string, etc.
****************/
{
/****************/
Boolean redisplay;
void* flow = new->rich_text.flow;
Boolean new_height = 0, new_string = 0;
int f;
/** This routine should only reformat the text once! **/
if(new->rich_text.value != current->rich_text.value){
XtFree(current->rich_text.value);
new_string = 1;
new->rich_text.value = XtNewString(new->rich_text.value);
new->rich_text.bytes = new->rich_text.value ? strlen(new->rich_text.value):0;
}
if(new->rich_text.fontList != current->rich_text.fontList){
CopyFontList(new);
new_string = 1;
}
if(new_string || new->rich_text.rtf != current->rich_text.rtf){
if(XTextView_string(flow,
new->rich_text.value,
new->rich_text.rtf))
new_height = 1;
redisplay = 1;
new->rich_text.point = new->rich_text.mark = 0;
}
if(new->core.width != current->core.width){
new_height = redisplay = 1;
}
if(new_height
|| new->rich_text.margin_width != current->rich_text.margin_width
|| new->rich_text.margin_height != current->rich_text.margin_height)
{
XTextView_resize(flow,
new->rich_text.margin_width,
new->rich_text.margin_height,
new->core.width - new->rich_text.margin_width*2,
32000); /* @# */
new->core.height = XTextView_height(flow) +
2 * new->rich_text.margin_height;
redisplay = 1;
}
return( redisplay ) ;
}
/****************************************************************/
Widget
XcCreateRichText(
Widget p, /* parent widget */
String name, /* widget name */
ArgList args, /* arg list */
Cardinal n) /* arg count */
/****************
* This function creates and returns a Rich Text widget.
****************/
{
/****************/
return( XtCreateWidget( name, xcRichTextWidgetClass, p, args, n)) ;
}
static void
MotionVerify(Widget w, XEvent* ev, String* dummy, Cardinal* unused)
{
XcRichTextWidget rt = (XcRichTextWidget)w;
XcRichTextCallbackStruct cb;
cb.reason = XmCR_INPUT;
cb.event = ev;
cb.window = XtWindow(rt);
cb.mark = rt->rich_text.mark;
cb.point = rt->rich_text.point;
cb.value = rt->rich_text.value;
XtCallCallbackList ((Widget) rt,
rt->rich_text.motion_verify_callback, (XtPointer) &cb) ;
}
static void
PrepareInvertGC(XcRichTextWidget w)
{
XGCValues values;
unsigned long valuemask = GCFunction | GCForeground;
if(w->rich_text.invert)
XtReleaseGC((Widget)w, w->rich_text.invert);
values.function = GXxor;
values.foreground = w->primitive.foreground ^ w->core.background_pixel;
w->rich_text.invert = XtGetGC((Widget)w, valuemask, &values);
}
static int
InvertSelection(XcRichTextWidget w)
{
int* x = w->rich_text.sx;
int* y = w->rich_text.sy;
if(w->rich_text.point != w->rich_text.mark){
if(y[3] > y[1]){
/* case 1:
* "score ... our" is selected:
*
* x0 x1 x2 x3
* | | | |_____y0
* | Four score and seven years_____y1,y2
* ago today, our forefathers |_____y3
* brought forth,
*/
XFillRectangle(XtDisplay((Widget)w), XtWindow((Widget)w),
w->rich_text.invert,
x[1], y[0], x[3]-x[1], y[1]-y[0]);
XFillRectangle(XtDisplay((Widget)w), XtWindow((Widget)w),
w->rich_text.invert,
x[0], y[2], x[2]-x[0], y[3]-y[2]);
if(y[2] > y[1])
/* case 3:
* "score ... brought" is selected:
*
* x0 x1
* | | _____y0
* | Four score and seven years_____y1
* ago today, our forefathers |_____y2
* brought forth, |_____y3
* | |
* x2 x3
*/
XFillRectangle(XtDisplay((Widget)w), XtWindow((Widget)w),
w->rich_text.invert,
x[0], y[1], x[3]-x[0], y[2]-y[1]);
}else{
/*
* case 3:
* "score and seven"
* x0 x1 x2 x3
* | | | |_____y0, y2
* | Four score and seven years_____y1, y3
* ago today, our forefathers
* brought forth,
*/
XFillRectangle(XtDisplay((Widget)w), XtWindow((Widget)w),
w->rich_text.invert,
x[1], y[0], x[2]-x[1], y[3]-y[0]);
}
}
}
static void
FillDifference(Display* disp,
Drawable d,
GC gc,
int x1, int y1, unsigned w1, unsigned h1,
int x2, int y2, unsigned w2, unsigned h2)
{
int xx1 = x1+w1;
int yy1 = y1+h1;
int xx2 = x2+w2;
int yy2 = y2+h2;
if(yy2<y1 || x2>xx2 || y2>yy1 || xx2<x1){
/* no intersection... */
XFillRectangle(disp, d, gc,
x1, y1, w1, h1);
} else
if(x2 <= x1 && xx2 >= xx1){
/* case 1: 0 horiz. intervals */
if(y2 <= y1 && yy2 >= yy1){
/* case 1a: 0 vert. intervals */
}else if (y2 > y1 && yy2 < yy1){
/* case 2b: 2 vert intervals */
XFillRectangle(disp, d, gc,
x1, y1, w1, y2-y1);
XFillRectangle(disp, d, gc,
x1, yy2, w1, yy1-yy2);
}else{
/* case 1c: 1 vert interval */
int y,h;
if(y2 > y1)
y = y1, h = y2-y1;
else
y = yy2, h = yy1-yy2;
XFillRectangle(disp, d, gc,
x1, y, w1, h);
}
}else if (x2 > x1 && xx2 < xx1){
/* case 2: 2 horiz intervals */
XFillRectangle(disp, d, gc,
x1, y1, x2-x1, h1);
XFillRectangle(disp, d, gc,
xx2, y1, xx1-xx2, h1);
if(y2 <= y1 && yy2 >= yy1){
/* case 2a: 0 vert. intervals */
}else if (y2 >y1 && yy2 < yy1){
/* case 2b: 2 vert intervals */
XFillRectangle(disp, d, gc,
x2, y1, w2, y2-y1);
XFillRectangle(disp, d, gc,
x2, yy2, w2, yy1-yy2);
}else{
/* case 2c: 1 vert interval */
int y,h;
if(y2 > y1)
y = y1, h = y2-y1;
else
y = yy2, h = yy1-yy2;
XFillRectangle(disp, d, gc,
x2, y, w2, h);
}
}else{
/* case 3: 1 horiz interval */
int x,w, xy, wy;
if(x2 > x1){
x = x1;
w = x2-x1;
xy = xx2;
wy = xx1-xx2;
}else{
x = xx2;
w = xx1-xx2;
xy = x1;
wy = x2-x1;
}
XFillRectangle(disp, d, gc,
x, y1, w, h1);
if(y2 <= y1 && yy2 >= yy1){
/* case 3a: 0 vert. intervals */
}else if (y2 >y1 && yy2 < yy1){
/* case 3b: 2 vert intervals */
XFillRectangle(disp, d, gc,
xy, y1, wy, y2-y1);
XFillRectangle(disp, d, gc,
xy, yy2, wy, yy1-yy2);
}else{
/* case 1c: 1 vert interval */
int y,h;
if(y2 > y1)
y = y1, h = y2-y1;
else
y = yy2, h = yy1-yy2;
XFillRectangle(disp, d, gc,
xy, y, wy, h);
}
}
}
static int
InvertDifference(XcRichTextWidget w,
int rx, int ry,
unsigned rw, unsigned rh)
{
int* x = w->rich_text.sx;
int* y = w->rich_text.sy;
if(w->rich_text.mark != w->rich_text.point){
if(y[3] > y[1]){
FillDifference(XtDisplay((Widget)w), XtWindow((Widget)w),
w->rich_text.invert,
x[1], y[0], x[3]-x[1], y[1]-y[0],
rx, ry, rw, rh);
FillDifference(XtDisplay((Widget)w), XtWindow((Widget)w),
w->rich_text.invert,
x[0], y[2], x[2]-x[0], y[3]-y[2],
rx, ry, rw, rh);
if(y[2] > y[1])
FillDifference(XtDisplay((Widget)w), XtWindow((Widget)w),
w->rich_text.invert,
x[0], y[1], x[3]-x[0], y[2]-y[1],
rx, ry, rw, rh);
}else{
FillDifference(XtDisplay((Widget)w), XtWindow((Widget)w),
w->rich_text.invert,
x[1], y[0], x[2]-x[1], y[3]-y[0],
rx, ry, rw, rh);
}
}
}
static void
SelectStart(Widget w, XEvent* ev, String* argv, Cardinal* argc)
{
XcRichTextWidget rt = (XcRichTextWidget)w;
XcRichTextPart* p = &rt->rich_text;
if(p->point != p->mark){
debug((" unselect old: \"%.*s\"\n",
p->point - p->mark,
p->value + p->mark));
InvertSelection(rt);
}
p->mark =
p->point = XTextView_position(p->flow,
ev->xbutton.x,
ev->xbutton.y);
debug(("set start = %ld (%c)\n",
p->point,
*(p->value + p->point)));
PrepareInvertGC(rt);
}
static void UpdateSelection(XcRichTextWidget rt, long h)
{
long pt = rt->rich_text.point;
long s, e;
if(pt == h)
return;
if(h < pt){
s = h;
e = pt;
}else{
s = pt;
e = h;
}
debug(("invert [%.*s]\n",
e-s,
rt->rich_text.value + s));
XTextView_region(rt->rich_text.flow, s, e,
rt->rich_text.sx,
rt->rich_text.sy);
rt->rich_text.point = h;
InvertSelection(rt);
}
static void
ExtendStart(Widget w, XEvent* ev, String* argv, Cardinal* argc)
{
XcRichTextWidget rt = (XcRichTextWidget)w;
XcRichTextPart* p = &rt->rich_text;
long h = XTextView_position(p->flow,
ev->xbutton.x,
ev->xbutton.y);
/* ASSUME: mark <= point */
if(abs(h - p->mark) <
abs(h - p->point)){
long tmp = p->mark;
p->mark = p->point;
p->point = tmp;
}
PrepareInvertGC(rt);
UpdateSelection(rt, h);
}
static void
ExtendAdjust(Widget w, XEvent* ev, String* argv, Cardinal* argc)
{
XcRichTextWidget rt = (XcRichTextWidget)w;
XcRichTextPart* p = &rt->rich_text;
long h = XTextView_position(p->flow,
ev->xbutton.x,
ev->xbutton.y);
UpdateSelection(rt, h);
}
static Boolean
ConvertSelection(Widget w,
Atom* selection,
Atom* target,
Atom* type,
XtPointer *value,
unsigned long *length,
int* format)
{
XcRichTextWidget rt = (XcRichTextWidget)w;
XcRichTextPart* p = &rt->rich_text;
if(*target == XmInternAtom(XtDisplay(w), "TARGETS", 1)){
*type = XA_ATOM;
*value = (XtPointer)XtNew(Atom);
*((Atom*)(*value)) = XA_STRING;
*length = 2;
*format = 32;
return TRUE;
}else if(*target == XA_STRING){
long l = p->point - p->mark;
*type = XA_STRING;
*value = XTextView_plain_text(p->value + p->mark, l);
*length = strlen(*value);
*format = 8;
return TRUE;
}
return FALSE;
}
static void
LoseSelection(Widget w, Atom* selection)
{
XcRichTextWidget rt = (XcRichTextWidget)w;
XcRichTextPart* p = &rt->rich_text;
if(p->point == p->mark)
return;
debug(("lose selection: [%.*s]\n",
p->point - p->mark,
p->value + p->mark));
InvertSelection(rt);
p->point = p->mark;
}
static void
ExtendEnd(Widget w, XEvent* ev, String* argv, Cardinal *argc)
{
XcRichTextWidget rt = (XcRichTextWidget)w;
XcRichTextPart* p = &rt->rich_text;
long h = XTextView_position(p->flow,
ev->xbutton.x,
ev->xbutton.y);
UpdateSelection(rt, h);
if(p->point < p->mark){
long tmp = p->mark;
p->mark = p->point;
p->point = tmp;
}
if(p->point > p->mark)
XTextView_region(p->flow, p->mark, p->point,
p->sx,
p->sy);
debug(("selection: [%.*s]\n",
p->point - p->mark,
p->value + p->mark));
{
Cardinal i;
for(i = 0; i<*argc; i++){
Atom selection = XmInternAtom(XtDisplay(w), argv[i], 0);
if(selection)
if(!XtOwnSelection(w, selection, ev->xbutton.time,
ConvertSelection, LoseSelection, NULL))
debug(("can't get selection: %s\n", argv[i]));
}
}
}
/* XTextView support */
XFontStruct*
Widget_font(void* w, const char* charset)
{
XcRichTextWidget rw = (XcRichTextWidget)w;
short indx;
XFontStruct* font;
if(!_XmFontListSearch(rw->rich_text.fontList,
(XmStringCharSet)charset,
&indx,
&font))
_XmFontListGetDefaultFont(rw->rich_text.fontList,
&font);
return font;
}
unsigned long
Widget_color(void* w, int r, int g, int b)
{
Colormap cm;
XcRichTextWidget rw = (XcRichTextWidget)w;
XColor c;
c.red = r;
c.green = g;
c.blue = b;
XtVaGetValues((Widget)rw,
XmNcolormap, &cm,
0);
if(XAllocColor(XtDisplay(rw), cm, &c))
return c.pixel;
else
return rw->primitive.foreground;
}
GC
Widget_get_gc(void* w, unsigned long mask, XGCValues* v)
{
return XtGetGC((Widget)w, mask, v);
}
void
Widget_free_gc(void* w, GC gc)
{
XtReleaseGC((Widget)w, gc);
}
/* text functions */
char *XcRichTextGetString(Widget widget)
{
XcRichTextWidget r = (XcRichTextWidget)widget;
return XtNewString(r->rich_text.value);
}
long XcRichTextGetLastPosition (Widget widget)
{
XcRichTextWidget r = (XcRichTextWidget)widget;
return r->rich_text.bytes;
}
char *XcRichTextGetSelection (Widget widget, int strip_rtf)
{
XcRichTextWidget r = (XcRichTextWidget)widget;
long l = r->rich_text.point - r->rich_text.mark;
if(l == 0)
return 0;
if(strip_rtf)
return XTextView_plain_text(r->rich_text.value + r->rich_text.mark, l);
else{
char* ret = XtMalloc(l+1);
strncpy(ret, r->rich_text.value + r->rich_text.mark, l);
ret[l] = 0;
return ret;
}
}
void XcRichTextSetSelection (Widget widget,
long first,
long last,
Time set_time)
{
XcRichTextWidget r = (XcRichTextWidget)widget;
Atom selection = XmInternAtom(XtDisplay(widget), "PRIMARY", 0); /* @@ */
LoseSelection(widget, 0);
if(first > r->rich_text.bytes || last > r->rich_text.bytes)
return;
r->rich_text.mark = r->rich_text.point = first;
UpdateSelection(r, last);
if(selection)
XtOwnSelection(widget, selection, set_time,
ConvertSelection, LoseSelection, NULL);
}
void XcRichTextClearSelection (Widget widget, Time clear_time)
{
LoseSelection(widget, 0);
}
Boolean XcRichTextGetSelectionPosition (Widget widget,
long *left,
long *right)
{
XcRichTextWidget r = (XcRichTextWidget)widget;
if(r->rich_text.point == r->rich_text.mark)
return 0;
*left = r->rich_text.mark;
*right = r->rich_text.mark;
return 1;
}
long XcRichTextXYToPos (Widget widget,
Position x, Position y)
{
XcRichTextWidget r = (XcRichTextWidget)widget;
return XTextView_position(r->rich_text.flow, x, y);
}
Boolean XcRichTextPosToXY (Widget widget,
long pos, Position *x, Position *y)
{
XcRichTextWidget r = (XcRichTextWidget)widget;
if(pos >= 0 && pos <= r->rich_text.bytes){
int yy;
*x = XTextView_locate(r->rich_text.flow, pos, &yy, 0);
*y = yy;
return 1;
}else
return 0;
}